home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 August (Alt) / CHIP 2005-08.1.iso / program / guvenlik / syslinux-3.07.exe / win32 / syslinux.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-12-28  |  12.1 KB  |  484 lines

  1. /* ----------------------------------------------------------------------- *
  2.  *   
  3.  *   Copyright 2003 Lars Munch Christensen - All Rights Reserved
  4.  *   Copyright 1998-2004 H. Peter Anvin - All Rights Reserved
  5.  *    
  6.  *   Based on the Linux installer program for SYSLINUX by H. Peter Anvin
  7.  *
  8.  *   This program is free software; you can redistribute it and/or modify
  9.  *   it under the terms of the GNU General Public License as published by
  10.  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  11.  *   Boston MA 02111-1307, USA; either version 2 of the License, or
  12.  *   (at your option) any later version; incorporated herein by reference.
  13.  *
  14.  * ----------------------------------------------------------------------- */
  15.  
  16. /*
  17.  * syslinux-mingw.c - Win2k/WinXP installer program for SYSLINUX
  18.  */
  19.  
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23.  
  24. #include "syslinux.h"
  25. #include "libfat.h"
  26.  
  27. #ifdef __GNUC__
  28. # define noreturn void __attribute__((noreturn))
  29. #else
  30. # define noreturn void
  31. #endif
  32.  
  33. void error(char* msg);
  34.  
  35. /* Begin stuff for MBR code */
  36.  
  37. #include <winioctl.h>
  38.  
  39. #define SECTOR_SIZE 512
  40. #define PART_TABLE  0x1be
  41. #define PART_SIZE   0x10
  42. #define PART_COUNT  4
  43. #define PART_ACTIVE 0x80
  44.  
  45. // The following struct should be in the ntddstor.h file, but I didn't have it.
  46. // TODO: Make this a conditional compilation
  47. typedef struct _STORAGE_DEVICE_NUMBER {
  48.   DEVICE_TYPE  DeviceType;
  49.   ULONG  DeviceNumber;
  50.   ULONG  PartitionNumber;
  51. } STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER;
  52.  
  53. BOOL GetStorageDeviceNumberByHandle( HANDLE handle, const STORAGE_DEVICE_NUMBER *sdn ) {
  54.   BOOL result = FALSE;
  55.   DWORD count;
  56.   
  57.   if ( DeviceIoControl( handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL,
  58.             0, (LPVOID)sdn, sizeof( *sdn ), &count, NULL ) ) {
  59.     result = TRUE;
  60.   }
  61.   else {
  62.     error("GetDriveNumber: DeviceIoControl failed");
  63.   }
  64.   
  65.   return( result );
  66. }
  67.  
  68. int GetBytesPerSector( HANDLE drive ) {
  69.   int result = 0;
  70.   DISK_GEOMETRY g;
  71.   DWORD count;
  72.   
  73.   if ( DeviceIoControl( drive, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
  74.             &g, sizeof( g ), &count, NULL ) ) {
  75.     result = g.BytesPerSector;
  76.   }
  77.   
  78.   return( result );
  79. }
  80.  
  81. BOOL FixMBR(int driveNum, int partitionNum, int write_mbr, int set_active) {
  82.   BOOL result = TRUE;
  83.   HANDLE drive;
  84.   
  85.   char driveName[128];
  86.   
  87.   sprintf( driveName, "\\\\.\\PHYSICALDRIVE%d", driveNum );
  88.   
  89.   drive = CreateFile( driveName,
  90.               GENERIC_READ | GENERIC_WRITE,
  91.               FILE_SHARE_WRITE | FILE_SHARE_READ,
  92.               NULL,
  93.               OPEN_EXISTING,
  94.               0,
  95.               NULL );
  96.   
  97.   if( drive == INVALID_HANDLE_VALUE ) {
  98.     error("Accessing physical drive");
  99.     result = FALSE;
  100.   }
  101.   
  102.   if( result ) {
  103.     unsigned char sector[SECTOR_SIZE];
  104.     DWORD howMany;
  105.     
  106.     if( GetBytesPerSector( drive ) != SECTOR_SIZE ) {
  107.       fprintf(stderr, "Error: Sector size of this drive is %d; must be %d\n",
  108.           GetBytesPerSector( drive ), SECTOR_SIZE );
  109.       result = FALSE;
  110.     }
  111.     
  112.     if ( result ) {
  113.       if ( ReadFile( drive, sector, sizeof( sector ), &howMany, NULL ) == 0 ) {
  114.     error("Reading raw drive");
  115.     result = FALSE;
  116.       } else if ( howMany != sizeof( sector ) ) {
  117.     fprintf(stderr, "Error: ReadFile on drive only got %d of %d bytes\n",
  118.         (int)howMany, sizeof( sector ) );
  119.     result = FALSE;
  120.       }
  121.     }
  122.     
  123.     // Copy over the MBR code if specified (-m)
  124.     if ( write_mbr ) {
  125.       if ( result ) {
  126.     if ( syslinux_mbr_len >= PART_TABLE ) {
  127.       fprintf(stderr, "Error: MBR will not fit; not writing\n" );
  128.       result = FALSE;
  129.     } else {
  130.       memcpy( sector, syslinux_mbr, syslinux_mbr_len );
  131.     }
  132.       }
  133.     }
  134.     
  135.     // Check that our partition is active if specified (-a)
  136.     if ( set_active ) {
  137.       if ( sector[ PART_TABLE + ( PART_SIZE * ( partitionNum - 1 ) ) ] != 0x80 ) {
  138.     int p;
  139.     for ( p = 0; p < PART_COUNT; p++ )
  140.       sector[ PART_TABLE + ( PART_SIZE * p ) ] = ( p == partitionNum - 1 ? 0x80 : 0 );
  141.       }
  142.     }
  143.  
  144.     if ( result ) {
  145.       SetFilePointer( drive, 0, NULL, FILE_BEGIN );
  146.       
  147.       if ( WriteFile( drive, sector, sizeof( sector ), &howMany, NULL ) == 0 ) {
  148.     error("Writing MBR");
  149.     result = FALSE;
  150.       } else if ( howMany != sizeof( sector ) ) {
  151.     fprintf(stderr, "Error: WriteFile on drive only wrote %d of %d bytes\n",
  152.         (int)howMany, sizeof( sector ) );
  153.     result = FALSE;
  154.       }
  155.     }
  156.     
  157.     if( !CloseHandle( drive ) ) {
  158.       error("CloseFile on drive");
  159.       result = FALSE;
  160.     }
  161.   }
  162.   
  163.   return( result );
  164. }
  165.  
  166. /* End stuff for MBR code */
  167.  
  168. const char *program;        /* Name of program */
  169. const char *drive;        /* Drive to install to */
  170.  
  171. /*
  172.  * Check Windows version.
  173.  *
  174.  * On Windows Me/98/95 you cannot open a directory, physical disk, or
  175.  * volume using CreateFile.
  176.  */
  177. int checkver(void)
  178. {
  179.   OSVERSIONINFO osvi;
  180.  
  181.   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  182.   GetVersionEx(&osvi);
  183.  
  184.   return  (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
  185.           ((osvi.dwMajorVersion > 4) ||
  186.           ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion == 0)));
  187. }
  188.  
  189. /*
  190.  * Windows error function
  191.  */
  192. void error(char* msg)
  193. {
  194.   LPVOID lpMsgBuf;
  195.  
  196.   /* Format the Windows error message */
  197.   FormatMessage( 
  198.         FORMAT_MESSAGE_ALLOCATE_BUFFER | 
  199.         FORMAT_MESSAGE_FROM_SYSTEM | 
  200.         FORMAT_MESSAGE_IGNORE_INSERTS,
  201.         NULL, GetLastError(),
  202.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  203.         (LPTSTR) &lpMsgBuf, 0, NULL );
  204.   
  205.   /* Print it */
  206.   fprintf(stderr, "%s: %s", msg, (char*) lpMsgBuf);
  207.  
  208.   /* Free the buffer */
  209.   LocalFree(lpMsgBuf);
  210. }
  211.  
  212. /*
  213.  * Wrapper for ReadFile suitable for libfat
  214.  */
  215. int libfat_readfile(intptr_t pp, void *buf, size_t secsize, libfat_sector_t sector)
  216. {
  217.   uint64_t offset = (uint64_t)sector * secsize;
  218.   LONG loword = (LONG)offset;
  219.   LONG hiword  = (LONG)(offset >> 32);
  220.   LONG hiwordx = hiword;
  221.   DWORD bytes_read;
  222.  
  223.   if ( SetFilePointer((HANDLE)pp, loword, &hiwordx, FILE_BEGIN) != loword ||
  224.        hiword != hiwordx ||
  225.        !ReadFile((HANDLE)pp, buf, secsize, &bytes_read, NULL) ||
  226.        bytes_read != secsize ) {
  227.     fprintf(stderr, "Cannot read sector %u\n", sector);
  228.     exit(1);
  229.   }
  230.  
  231.   return secsize;
  232. }
  233.  
  234. noreturn usage(void)
  235. {
  236.   fprintf(stderr, "Usage: syslinux.exe [-sfma] <drive>: [bootsecfile]\n");
  237.   exit(1);
  238. }
  239.  
  240. int main(int argc, char *argv[])
  241. {
  242.   HANDLE f_handle, d_handle;
  243.   DWORD bytes_read;
  244.   DWORD bytes_written;
  245.   DWORD drives;
  246.   UINT drive_type;
  247.  
  248.   static unsigned char sectbuf[512];
  249.   char **argp, *opt;
  250.   static char drive_name[] = "\\\\.\\?:";
  251.   static char drive_root[] = "?:\\";
  252.   static char ldlinux_name[] = "?:\\ldlinux.sys" ;
  253.   const char *errmsg;
  254.   struct libfat_filesystem *fs;
  255.   libfat_sector_t s, *secp, sectors[65]; /* 65 is maximum possible */
  256.   uint32_t ldlinux_cluster;
  257.   int nsectors;
  258.   const char *bootsecfile = NULL;
  259.  
  260.   int force = 0;        /* -f (force) option */
  261.   int mbr = 0;            /* -m (MBR) option */
  262.   int setactive = 0;        /* -a (set partition active) */
  263.  
  264.   (void)argc;
  265.  
  266.   if (!checkver()) {
  267.     fprintf(stderr, "You need to be running at least Windows NT; use syslinux.com instead.\n");
  268.     exit(1);
  269.   }
  270.  
  271.   program = argv[0];
  272.   drive = NULL;
  273.  
  274.   for ( argp = argv+1 ; *argp ; argp++ ) {
  275.     if ( **argp == '-' ) {
  276.       opt = *argp + 1;
  277.       if ( !*opt )
  278.     usage();
  279.  
  280.       while ( *opt ) {
  281.     switch ( *opt ) {
  282.     case 's':        /* Use "safe, slow and stupid" code */
  283.       syslinux_make_stupid();
  284.       break;
  285.     case 'f':        /* Force install */
  286.       force = 1;   
  287.       break;
  288.     case 'm':        /* Install MBR */
  289.       mbr = 1;
  290.       break;
  291.     case 'a':        /* Mark this partition active */
  292.       setactive = 1;
  293.       break;
  294.     default:
  295.       usage();
  296.       break;
  297.     }
  298.     opt++;
  299.       }
  300.     } else {
  301.       if ( bootsecfile )
  302.     usage();
  303.       else if ( drive )
  304.     bootsecfile = *argp;
  305.       else
  306.     drive = *argp;
  307.     }
  308.   }
  309.  
  310.   if ( !drive || !isalpha(drive[0]) || drive[1] != ':' || drive[2] )
  311.     usage();
  312.  
  313.   /* Test if drive exists */
  314.   drives = GetLogicalDrives();
  315.   if(!(drives & ( 1 << (tolower(drive[0]) - 'a')))) {
  316.     fprintf(stderr, "No such drive %c:\n", drive[0]);
  317.     exit(1);
  318.   }
  319.  
  320.   /* Determines the drive type */
  321.   drive_name[4]   = drive[0];
  322.   ldlinux_name[0] = drive[0];
  323.   drive_root[0]   = drive[0];
  324.   drive_type = GetDriveType(drive_root);
  325.  
  326.   /* Test for removeable media */
  327.   if ((drive_type == DRIVE_FIXED) && (force == 0)) {
  328.     fprintf(stderr, "Not a removable drive (use -f to override) \n");
  329.     exit(1);
  330.   }
  331.  
  332.   /* Test for unsupported media */
  333.   if ((drive_type != DRIVE_FIXED) && (drive_type != DRIVE_REMOVABLE)) {
  334.     fprintf(stderr, "Unsupported media\n");
  335.     exit(1);
  336.   }
  337.  
  338.   /*
  339.    * First open the drive
  340.    */
  341.   d_handle = CreateFile(drive_name, GENERIC_READ | GENERIC_WRITE,
  342.              FILE_SHARE_READ | FILE_SHARE_WRITE,
  343.              NULL, OPEN_EXISTING, 0, NULL );
  344.  
  345.   if (d_handle == INVALID_HANDLE_VALUE) {
  346.     error("Could not open drive");
  347.     exit(1);
  348.   }
  349.  
  350.   /*
  351.    * Make sure we can read the boot sector
  352.    */  
  353.   if ( !ReadFile(d_handle, sectbuf, 512, &bytes_read, NULL) ) {
  354.     error("Reading boot sector");
  355.     exit(1);
  356.   }
  357.   if (bytes_read != 512) {
  358.     fprintf(stderr, "Could not read the whole boot sector\n");
  359.     exit(1);
  360.   }
  361.   
  362.   /* Check to see that what we got was indeed an MS-DOS boot sector/superblock */
  363.   if( (errmsg = syslinux_check_bootsect(sectbuf)) ) {
  364.     fprintf(stderr, "%s\n", errmsg);
  365.     exit(1);
  366.   }
  367.  
  368.   /* Change to normal attributes to enable deletion */
  369.   /* Just ignore error if the file do not exists */
  370.   SetFileAttributes(ldlinux_name, FILE_ATTRIBUTE_NORMAL);
  371.  
  372.   /* Delete the file */
  373.   /* Just ignore error if the file do not exists */
  374.   DeleteFile(ldlinux_name);
  375.  
  376.   /* Create ldlinux.sys file */
  377.   f_handle = CreateFile(ldlinux_name, GENERIC_READ | GENERIC_WRITE,
  378.             FILE_SHARE_READ | FILE_SHARE_WRITE,
  379.             NULL, CREATE_ALWAYS, 
  380.             FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM |
  381.             FILE_ATTRIBUTE_HIDDEN,
  382.             NULL );
  383.   
  384.   if (f_handle == INVALID_HANDLE_VALUE) {
  385.     error("Unable to create ldlinux.sys");
  386.     exit(1);
  387.   }
  388.  
  389.   /* Write ldlinux.sys file */
  390.   if (!WriteFile(f_handle, syslinux_ldlinux, syslinux_ldlinux_len, &bytes_written, NULL)) {
  391.     error("Could not write ldlinux.sys");
  392.     exit(1);
  393.   }
  394.  
  395.   if (bytes_written != syslinux_ldlinux_len) {
  396.     fprintf(stderr, "Could not write whole ldlinux.sys\n");
  397.     exit(1);
  398.   }
  399.  
  400.   /* Now flush the media */
  401.   if(!FlushFileBuffers(f_handle)) {
  402.     error("FlushFileBuffers failed");
  403.     exit(1);
  404.   }
  405.  
  406.   /* Map the file (is there a better way to do this?) */
  407.   fs = libfat_open(libfat_readfile, (intptr_t)d_handle);
  408.   ldlinux_cluster = libfat_searchdir(fs, 0, "LDLINUX SYS", NULL);
  409.   secp = sectors;
  410.   nsectors = 0;
  411.   s = libfat_clustertosector(fs, ldlinux_cluster);
  412.   while ( s && nsectors < 65 ) {
  413.     *secp++ = s;
  414.     nsectors++;
  415.     s = libfat_nextsector(fs, s);
  416.   }
  417.   libfat_close(fs);
  418.  
  419.   /*
  420.    * Patch ldlinux.sys and the boot sector
  421.    */
  422.   syslinux_patch(sectors, nsectors);
  423.  
  424.   /*
  425.    * Rewrite the file
  426.    */
  427.   if ( SetFilePointer(f_handle, 0, NULL, FILE_BEGIN) != 0 ||
  428.        !WriteFile(f_handle, syslinux_ldlinux, syslinux_ldlinux_len, &bytes_written, NULL) ||
  429.        bytes_written != syslinux_ldlinux_len ) {
  430.     error("Could not write ldlinux.sys");
  431.     exit(1);
  432.   }
  433.  
  434.   /* If desired, fix the MBR */
  435.   if( mbr || setactive ) {
  436.     STORAGE_DEVICE_NUMBER sdn;
  437.     if( GetStorageDeviceNumberByHandle( d_handle, &sdn ) ) {
  438.       if( !FixMBR(sdn.DeviceNumber, sdn.PartitionNumber, mbr, setactive) ) {
  439.         fprintf(stderr, "Did not successfully update the MBR; continuing...\n");
  440.       }
  441.     } else {
  442.       fprintf(stderr, "Could not find device number for updating MBR; continuing...\n");
  443.     }
  444.   }
  445.  
  446.   /* Close file */ 
  447.   CloseHandle(f_handle);
  448.  
  449.   /* Make the syslinux boot sector */
  450.   syslinux_make_bootsect(sectbuf);
  451.  
  452.   /* Write the syslinux boot sector into the boot sector */
  453.   if ( bootsecfile ) {
  454.     f_handle = CreateFile(bootsecfile, GENERIC_READ | GENERIC_WRITE,
  455.               FILE_SHARE_READ | FILE_SHARE_WRITE,
  456.               NULL, CREATE_ALWAYS, 
  457.               FILE_ATTRIBUTE_ARCHIVE,
  458.               NULL );
  459.     if (f_handle == INVALID_HANDLE_VALUE) {
  460.       error("Unable to create bootsector file");
  461.       exit(1);
  462.     }
  463.     if (!WriteFile(f_handle, sectbuf, 512, &bytes_written, NULL)) {
  464.       error("Could not write boot sector file");
  465.       exit(1);
  466.     }
  467.     CloseHandle(f_handle);
  468.   } else {
  469.     SetFilePointer(d_handle, 0, NULL, FILE_BEGIN);
  470.     WriteFile( d_handle, sectbuf, 512, &bytes_written, NULL ) ;
  471.   }
  472.  
  473.   if(bytes_written != 512) {
  474.     fprintf(stderr, "Could not write the whole boot sector\n");
  475.     exit(1);
  476.   }
  477.   
  478.   /* Close file */ 
  479.   CloseHandle(d_handle);
  480.  
  481.   /* Done! */
  482.   return 0;
  483. }
  484.